#include "ui.hpp"


void ManShellUI::m_init(){
	m_titel = "NULL";
	m_result = "\n";
	m_quit = false;
	m_fifo = 0;
	m_page = 0;
	m_max = MAN_LINESIZE;
};

ManShellUI::ManShellUI(){
	m_init();
};

ManShellUI::ManShellUI(string titel){
	m_init();
	m_titel = titel + MAN_OP;
};

ManShellUI::~ManShellUI(){
	m_quit = true;
	
	if (m_thread.joinable()){
		m_thread.join();
	}
	
	if (m_threadfifo.joinable()){
		pthread_cancel(m_threadfifo.native_handle());
		m_threadfifo.join();
	}

	if(m_fifo > 0){
		close(m_fifo);	
	}
	system("clear");
};

void ManShellUI::update(){

	int page_count = m_max;
	int page = 0;
	std::vector<std::string> sList;
	
	splitStr(m_result,"\n",sList);
	
	page = sList.size() / page_count;
	if(m_page > page)
		m_page = page;
		
	page_count = page_count + (m_page * m_max);
	system("clear");
	
	cout<<"\033[42m" + to_string(page) + "/" + to_string(m_page) + ">  " + m_titel +  "\n\033[0m"<<endl;
	for (int i = m_page * m_max;i < page_count && i <  sList.size(); i++) {
		cout << sList.at(i) << endl;
	}
};

void ManShellUI::loop(){
#ifdef MAN_LOOP_UPDATE
	while(!m_quit){
		update();
		usleep(1000 * 16); // 60 fps,忽略 update 耗时，粗略计算
	};
#else
	update();

#endif
};

void ManShellUI::loopFIFO(){
	int n = 0;
	char buf[1000] = {0};
	string ouput;
		
	while(!m_quit){
		n = read(m_fifo,buf,sizeof(buf) - 1);
		if(n <= 0){
			usleep(1000);
			continue;
		}
		buf[n] = '\0';
		setResult(buf);
#ifndef MAN_LOOP_UPDATE
		update();
#endif
	};
};


void ManShellUI::threadFunc(ManShellUI* ptr){
	ptr->loop();
}

void ManShellUI::threadFuncFIFO(ManShellUI* ptr){
	ptr->loopFIFO();
}

void ManShellUI::start(){
	m_thread = thread(threadFunc,this);
	return;
}

void ManShellUI::start(string fifo){
	int n = 0;
	int ret = 0;
	ret = access(fifo.c_str(),F_OK);
	if(!ret){
		if(remove(fifo.c_str()) != 0){
			cout << "remove error" + fifo << endl;
			return;
		}
	}
	ret = mkfifo(fifo.c_str(),0777);
	if(ret < 0){
		cout << "mkfifo error" + fifo << endl;
		return;
	}
	
	m_fifo = open(fifo.c_str(),O_RDWR);
	if(m_fifo <= 0){
		cout << "open fifo err: " + fifo << endl;
		return;
	}
	m_thread = thread(threadFunc,this);
	m_threadfifo = thread(threadFuncFIFO,this);
	return;
}

void ManShellUI::setTitel(string titel){
	m_titel = titel;
	m_titel = titel + MAN_OP;
#ifndef MAN_LOOP_UPDATE
	update();
#endif
	return;
}

void ManShellUI::setResult(string result){
	cout << result << endl;
	m_result += result;
#ifndef MAN_LOOP_UPDATE
	update();
#endif
	return;
}

void ManShellUI::clearResult(){
	m_result = "";
#ifndef MAN_LOOP_UPDATE
	update();
#endif
	return;
}

void ManShellUI::setPage(int page){
	if(page < 0)
		return;
	m_page = page;
#ifndef MAN_LOOP_UPDATE
	update();
#endif
	return;
}

int ManShellUI::getPage(){
	return m_page;
}

void ManShellUI::setPageMax(int count){
	if(count < 0)
		return;
	m_max = count;
#ifndef MAN_LOOP_UPDATE
	update();
#endif
	return;
}
